package com.sl.sdn.repository.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.extra.mail.MailUtil;
import com.sl.sdn.dto.OrganDTO;
import com.sl.sdn.dto.TransportLineNodeDTO;
import com.sl.sdn.entity.node.AgencyEntity;
import com.sl.sdn.enums.OrganTypeEnum;
import com.sl.sdn.repository.TransportLineRepository;
import org.bouncycastle.util.test.TestRandomData;
import org.neo4j.driver.Value;
import org.neo4j.driver.internal.value.PathValue;
import org.neo4j.driver.types.Path;
import org.springframework.data.neo4j.core.Neo4jClient;
import org.springframework.stereotype.Repository;

import javax.annotation.Resource;
import java.util.Map;
import java.util.Optional;

/**
 * description:
 *
 * @Author youhongwei
 * @Create 2025/6/23 18:35
 * @Version 1.0
 */
@Repository
public class TransportLineRepositoryImpl implements TransportLineRepository {

    @Resource
    private Neo4jClient neo4jClient;

    @Override
    public TransportLineNodeDTO findShortestPath(AgencyEntity start, AgencyEntity end) {

        String cyperStr = "MATCH path = shortestPath((n:AGENCY) -[*..10]->(m:AGENCY))\n" +
                "WHERE n.bid = $startId AND m.bid = $endId RETURN path";

        Optional<TransportLineNodeDTO> optional = this.neo4jClient.query(cyperStr)
                // 绑定参数
                .bind(start.getBid()).to("startId")
                .bind(end.getBid()).to("endId")
                // 将结果映射为TransportLineNodeDTO对象
                .fetchAs(TransportLineNodeDTO.class)
                .mappedBy((typeSystem, record) -> {
                    // 创建目标DTO对象
                    TransportLineNodeDTO dto = new TransportLineNodeDTO();
                    //处理路径中的节点
                    PathValue pathValue = (PathValue) record.get(0); // 获取查询返回的第一列（path
                    Path path = pathValue.asPath();// 转换为Path对象
                    //获取所有的结点
                    path.nodes().forEach(node -> {
                        // 将节点属性转为Map
                        Map<String,Object> map = node.asMap();
                        // 将Map转换为OrganDTO对象（使用工具类）
                        OrganDTO organDTO = BeanUtil.toBeanIgnoreError(map,OrganDTO.class);
                        //Agency TLT
                        String first = CollUtil.getFirst(node.labels()); // 获取第一个标签

                        organDTO.setType(OrganTypeEnum.valueOf(first).getCode()); // 转换为枚举编码
                        // 处理地理位置信息（假设有location属性）
                        Object location = map.get("location");
                        organDTO.setLongitude(BeanUtil.getProperty(location,"x"));//获取经度
                        organDTO.setLatitude(BeanUtil.getProperty(location,"y"));//获取纬度
                        // 将节点添加到DTO的节点列表
                        dto.getNodeList().add(organDTO);
                    });
                    //获取路径
                    path.relationships().forEach(relationship -> {
                        //取得relationship下面所有的属性
                        //获取路径的量成本
                        Map<String,Object> map = relationship.asMap();
                        //叠加
                        Double cost = MapUtil.getDouble(map, "cost");
                        dto.setCost(dto.getCost()+cost);
                    });

                    return dto;
                }).one();
        return optional.get();
    }



    @Override
    public TransportLineNodeDTO findShortestPath1(AgencyEntity start, AgencyEntity end) {

        // 修改Cypher查询以寻找成本最低的路径而不是最短路径
        String cyperStr = "MATCH path = (n:AGENCY)-[*..10]->(m:AGENCY) " +
                "WHERE n.bid = $startId AND m.bid = $endId " +
                "WITH path, reduce(cost = 0, r in relationships(path) | cost + r.cost) AS totalCost " +
                "ORDER BY totalCost ASC " +  // 按总成本升序排序
                "LIMIT 1 " +  // 只返回成本最低的一条路径
                "RETURN path, totalCost";

        Optional<TransportLineNodeDTO> optional = this.neo4jClient.query(cyperStr)
                // 绑定参数
                .bind(start.getBid()).to("startId")
                .bind(end.getBid()).to("endId")
                // 将结果映射为TransportLineNodeDTO对象
                .fetchAs(TransportLineNodeDTO.class)
                .mappedBy((typeSystem, record) -> {
                    // 创建目标DTO对象
                    TransportLineNodeDTO dto = new TransportLineNodeDTO();
                    //处理路径中的节点
                    PathValue pathValue = (PathValue) record.get(0); // 获取查询返回的第一列（path
                    Path path = pathValue.asPath();// 转换为Path对象
                    //获取所有的结点
                    path.nodes().forEach(node -> {
                        // 将节点属性转为Map
                        Map<String,Object> map = node.asMap();
                        // 将Map转换为OrganDTO对象（使用工具类）
                        OrganDTO organDTO = BeanUtil.toBeanIgnoreError(map,OrganDTO.class);
                        //Agency TLT
                        String first = CollUtil.getFirst(node.labels()); // 获取第一个标签

                        organDTO.setType(OrganTypeEnum.valueOf(first).getCode()); // 转换为枚举编码
                        // 处理地理位置信息（假设有location属性）
                        Object location = map.get("location");
                        organDTO.setLongitude(BeanUtil.getProperty(location,"x"));//获取经度
                        organDTO.setLatitude(BeanUtil.getProperty(location,"y"));//获取纬度
                        // 将节点添加到DTO的节点列表
                        dto.getNodeList().add(organDTO);
                    });
                    //获取路径
                    path.relationships().forEach(relationship -> {
                        //取得relationship下面所有的属性
                        //获取路径的量成本
                        Map<String,Object> map = relationship.asMap();
                        //叠加
                        Double cost = MapUtil.getDouble(map, "cost");
                        dto.setCost(dto.getCost()+cost);
                    });

                    return dto;
                }).one();
        return optional.get();
    }
}
